package com.managertrade.service.impl;

import com.managertrade.common.ErrorCode;
import com.managertrade.common.ServiceException;
import com.managertrade.dto.SysRoleDTO;
import com.managertrade.dto.vo.MenuVO;
import com.managertrade.dao.mysql.entity.SysMenu;
import com.managertrade.dao.mysql.entity.SysRole;
import com.managertrade.dao.mysql.entity.SysRoleMenu;
import com.managertrade.dao.mysql.entity.SysUserRole;
import com.managertrade.dao.mysql.repository.SysMenuRepository;
import com.managertrade.dao.mysql.repository.SysRoleMenuRepository;
import com.managertrade.dao.mysql.repository.SysRoleRepository;
import com.managertrade.dao.mysql.repository.SysUserRoleRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService{
    private final SysRoleRepository roleRepository;
    private final SysRoleMenuRepository  sysRoleMenuRepository;
    private final  MenuService menuService;
    private final SysUserRoleRepository sysUserRoleRepository;
    private final SysMenuRepository sysMenuRepository;

    @Override
    public List<SysRole> getAllRoles() {
        return roleRepository.findAll();
    }

    @Override
    public void addRole(SysRoleDTO role) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(role,sysRole);
        roleRepository.save(sysRole);
    }

    @Override
    public void updateRole(SysRoleDTO role) {
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(role,sysRole);
        roleRepository.save(sysRole);
    }

    @Override
    @Transactional
    public void deleteRole(Long id) {
        //查找当前角色是否绑定用户，如果有绑定，不能删除，需要接触绑定关系
        List<SysUserRole> SysUserRoleList = sysUserRoleRepository.findByroleId(id);
        if(!CollectionUtils.isEmpty(SysUserRoleList)){
            throw  new ServiceException(ErrorCode.ROLE_EXIT_USER);
        }
        roleRepository.deleteById(id);
        List<SysRoleMenu> roleMenus = sysRoleMenuRepository.findByRoleId(id);
        if(!CollectionUtils.isEmpty(roleMenus)){
            sysRoleMenuRepository.deleteInBatch(roleMenus);
        }
    }

    @Override
    public Map<String, Object> getRolePermissions(Long roleId) {
        List<MenuVO> menuTreeAll = menuService.getMenuTreeAll();
        List<Long> collectRoleId = menuService.getMenuRoleId(roleId).stream().map(k -> k.getId()).collect(Collectors.toList());
        Map<String, Object> map = new HashMap<>();
        map.put("checkedKeys",  collectRoleId == null ? new ArrayList<>() : collectRoleId);
        map.put("allPermissions", menuTreeAll);
        return map;
    }

    @Override
    @Transactional
    public void updateRolePermissions(Long roleId, List<Long> permissionIds) {
        // 删除旧的
        List<SysRoleMenu> roleMenus = sysRoleMenuRepository.findByRoleId(roleId);
        if (!CollectionUtils.isEmpty(roleMenus)) {
            sysRoleMenuRepository.deleteInBatch(roleMenus);
        }

        // 取出所有菜单，并构建 id -> parentId 映射
        List<SysMenu> allMenus = sysMenuRepository.findAll();
        Map<Long, Long> idToParentMap = allMenus.stream()
                .collect(Collectors.toMap(SysMenu::getId, SysMenu::getParentId));

        Set<Long> allPermissionIds = new HashSet<>(permissionIds);

        // 对每一个选中的节点，循环向上查找父节点
        for (Long id : permissionIds) {
            Long parentId = idToParentMap.get(id);
            while (parentId != null && parentId != 0 && allPermissionIds.add(parentId)) {
                parentId = idToParentMap.get(parentId); // 继续向上找
            }
        }

        // 批量保存
        List<SysRoleMenu> toSave = allPermissionIds.stream().map(menuId -> {
            SysRoleMenu rm = new SysRoleMenu();
            rm.setRoleId(roleId);
            rm.setMenuId(menuId);
            return rm;
        }).collect(Collectors.toList());

        sysRoleMenuRepository.saveAll(toSave);
    }

    @Override
    public List<SysRole> findSysRoleByUser(Long id) {
        List<SysUserRole> SysUserRoleList = sysUserRoleRepository.findByUserId(id);
        List<SysRole> list = new ArrayList<>();
        if(!CollectionUtils.isEmpty(SysUserRoleList)){
            list = roleRepository.findAllById(SysUserRoleList.stream().map(k -> k.getRoleId()).collect(Collectors.toList()));
        }
        return list;
    }
}
